﻿using System;
using System.Drawing;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using com.atiia.automation.sensors;

namespace NetFTsampleCsharp
{
    public partial class Form1 : Form
    {
        private double[] m_daftMaxes = { 100, 100, 100, 100, 100, 100 }; /*maximum
     rated force/torque readings*/
        private double[] m_daftCountsPerUnit = { 1000000, 1000000, 1000000, 1000000, 1000000, 1000000 }; /*counts per
        *unit force or torque for each axis*/
        /** Visualizes the forces and torques. */

        private String m_strForceUnits; /*The units of force.*/
        private String m_strTorqueUnits; /*The units of torque.*/
        private String m_strCalSN;
        private String m_strCalIndex;
        private String m_strCfgName;
        private String m_strCfgIndex;

        //private JLabel[] m_lblaFTLabel; /*the labels that display the force/torque
        //readings*/
        private String m_strSensorAddress; /*The network address of the sensor.*/
        //private JProgressBar[] m_progaFTReadingBar; /*the progress bars */
        private static int NUM_FT_AXES = 6;
        private static Color POSITIVE_COLOR = Color.Blue, NEGATIVE_COLOR = Color.Green;
        //private DecimalFormat m_dfReading;
        private NetFTSensor m_netFT; /*the Net F/T controller*/
        private NetFTReaderThread m_NetFTReaderThread = null; /*reads
     Net F/T in a loop*/
        private static Socket m_cNetFTDataSocket; /*socket used for high-speed
                                                *data collection*/
        private static bool m_bDoingHighSpeedCollection = false; /*whether or not
    *we're currently doing high speed data collection*/
        //private static java.io.PrintWriter m_cDataWriter; /*writes high-speed data to
        //file*/
        /** The RDT sample rate of the sensor. */
        private int m_iRDTSampleRate = 0;

        /**Thread which communicates with Net F/T
         */
        class NetFTReaderThread
        {
            private Thread thisThread;

            private NetFTSensor m_netFT; /*the Net F/T controller*/
            private Form1 m_guiParent; /*the gui that is using this
                                           *thread*/

            private bool m_bKeepGoing = true; /*controls when to end this
                                              *thread*/

            public void Start() { thisThread.Start(); }

            // thread gui
            Form threadForm;
            TextBox threadBox;

            /**
             * Creates a new Net F/T reader thread
             * @param setNetFT The initialized NetFTSensor to communicate with.
             * @param setParent The NetFTSampleGUI that is using this thread to
             * communicate with the Net F/T.
             */
            public NetFTReaderThread(NetFTSensor setNetFT, Form1 setParent)
            {
                m_netFT = setNetFT;
                m_guiParent = setParent;

                thisThread = new Thread(run);
            }

            /**Sets a flag to stop after the current read is complete*/
            public void stopReading()
            {
                m_bKeepGoing = false;
                thisThread.Interrupt(); /*wake this thread up if it's in it's sleeping
                               *phase*/
            }

            /**Reads the Net F/T sensor in a loop*/
            public void run()
            {
                threadForm = new Form();
                threadForm.Size = new Size(500, 500);
                threadForm.Visible = true;

                threadBox = new TextBox();
                threadBox.Font = new Font("Arial", 20);
                threadBox.Dock = DockStyle.Fill;
                threadBox.Multiline = true;
                threadForm.Controls.Add(threadBox);

                NetFTRDTPacket cRDTData; /*the latest f/t data from the Net F/T*/
                while (m_bKeepGoing)
                {
                    try
                    {
                        /*synchronize this in case they press the stop button
                             *while we're in the middle of reading the data*/
                        lock (m_netFT)
                        {
                            if (m_bDoingHighSpeedCollection)
                            {
                                /*read batch RDT packets*/
                                int PACKETS_TO_READ = 1000;
                                NetFTRDTPacket[] caRDTPackets = new NetFTRDTPacket[PACKETS_TO_READ];
                                caRDTPackets = m_netFT.readHighSpeedData(m_cNetFTDataSocket, PACKETS_TO_READ);
                                int i; /*generic loop/array index*/
                                /*Precondition: caRDTPackets contains the list of
                                 *packets that were read from the Net F/T.
                                *m_cDataWriter is open to file to collect data to.
                                *Postcondition: m_cDataWriter has the new F/T data.
                                *i == PACKETS_TO_READ.
                                */
                                for (i = 0; i < PACKETS_TO_READ; i++)
                                {
                                    Console.WriteLine(dataCollectionLine(caRDTPackets[i]));
                                    //m_cDataWriter.println( dataCollectionLine( caRDTPackets[i] ) );
                                }
                                cRDTData = caRDTPackets[PACKETS_TO_READ - 1];
                            }
                            else
                            {
                                cRDTData = m_netFT.readSingleFTRecord(threadBox);
                            }
                        }
                        m_guiParent.displayFTData(cRDTData, threadBox);
                    }
                    catch (SocketException sexc)
                    {
                        m_guiParent.displayError("Socket Exception: " + sexc.Message);
                    }
                    catch (IOException iexc)
                    {
                        m_guiParent.displayError("IO Exception: " +
                                iexc.Message);
                    }
                    try
                    {
                        if (!m_bDoingHighSpeedCollection)
                        {
                            Thread.Sleep(1000);
                        }
                    }
                    catch (Exception iexc)
                    {
                        /*do nothing, just continue.  This exception should
                         only be thrown if they try to stop the thread while
                         it's sleeping*/
                    }
                }
            }
        }

        /**Formats a data packet for collection to file.
         * @param nftrdtp   The data packet to record to file.
         * @return  A formatted string containing the F/T data and current time,
         * which can be written to file.
         */
        private static String dataCollectionLine(NetFTRDTPacket nftrdtp)
        {
            String outputString =  /* The formatted output line. */
                    "0x" + Convert.ToString(nftrdtp.getStatus(), 16) + "," +
                    nftrdtp.getRDTSequence() + "," +
                    nftrdtp.getFTSequence() + "," +
                    nftrdtp.getFx() + "," +
                    nftrdtp.getFy() + "," +
                    nftrdtp.getFz() + "," +
                    nftrdtp.getTx() + "," +
                    nftrdtp.getTy() + "," +
                    nftrdtp.getTz() + "," +
                    DateTime.Now.Ticks;
            return outputString;
        }

        /**
         * Stops the F/T reader thread, and sets m_NetFTReaderThread =
         * null.
         */
        private void stopReaderThread()
        {
            if (null != m_NetFTReaderThread)
            {
                m_NetFTReaderThread.stopReading();
                m_NetFTReaderThread = null;
            }
        }

        /**Stops (if necessary) the net f/t reader thread, and restarts it using
         *the user options. Also sets the scaling factors for the f/t display.
         */
        private void stopAndRestartSingleReadings()
        {
            if (null != m_NetFTReaderThread)
            {
                m_NetFTReaderThread.stopReading();
                m_NetFTReaderThread = null;
            }
            try
            {
                m_netFT = new NetFTSensor(System.Net.IPAddress.Parse(m_strSensorAddress));
            }
            catch (Exception uhex)
            {
                displayError("Unknown Host Exception: " + uhex.Message);
                return;
            }
            //if ( ! readConfigurationInfo() ) {
            //    return;
            //}
            //lblForceUnits.setText( "Force Units: " + m_strForceUnits );
            //lblTorqueUnits.setText( "Torque Units: " + m_strTorqueUnits );
            //lblCalIndex.setText("Calibration Index: " + (Integer.parseInt(m_strCalIndex) + 1));
            //lblConfigIndex.setText("Config Index: " + (Integer.parseInt(m_strCfgIndex) + 1));
            //lblCalSN.setText("Calibration Serial#: " + m_strCalSN);
            //lblConfigName.setText("Config Name: " + m_strCfgName);
            m_NetFTReaderThread = new NetFTReaderThread(m_netFT, this);
            m_NetFTReaderThread.Start();
            outputBox.AppendText("readerThread started");
        }

        ///**
        // *Reads a page from the integrated web server.
        // *@param strUrlSuffix   The page on the web server to read.
        // *@return  The text of the web page.
        // *@throws MalformedURLException If strUrlSuffix doesn't point to a valid
        // *web page address.
        // *@throws IOException If there is an error reading the web page text.
        // */
        //private String readWebPageText( String strUrlSuffix )
        //{
        //    /*Reads the HTML from the web server.*/
        //    BufferedReader cBufferedReader;
        //    /*The url of the configuration page.*/
        //    String strURL = "http://" + m_strSensorAddress + "/" +
        //            strUrlSuffix;
        //    cBufferedReader = new BufferedReader ( new InputStreamReader ( new
        //            URL(strURL).openConnection().getInputStream()));
        //    /*The text of the page.*/
        //    String strPageText = "";
        //    /*The last line read from the web stream.*/
        //    String strCurLine;
        //    /*Precondition: cBufferedReader is at the beginning of the page.
        //     *Postcondition: cBufferedReader is finished, strPageText =
        //     *the text of the page, strCurLine = last line read from the
        //     *page.
        //     */
        //     while ( null != ( strCurLine = cBufferedReader.readLine() ) ) {
        //        strPageText += strCurLine;
        //     }
        //    return strPageText;
        //}

        //private String readNetFTAPI(int index)
        //{
        //    try{
        //    String strXML = readWebPageText("netftapi2.xml?index="+index);
        //    return strXML;
        //    }catch(Exception e)
        //    {
        //        return "";
        //    }
        //}

        //    private String readNetFTCalAPI(int index)
        //{
        //    try{
        //    String strXML = readWebPageText("netftcalapi.xml?index="+index);
        //    return strXML;
        //    }catch(Exception e)
        //    {
        //        return "";
        //    }
        //}

        //private int findActiveCFG(String xmlText)
        //{
        //   String[] strret = xmlText.split("<setcfgsel>");
        //   String[] strret2 = strret[1].split("</setcfgsel>");
        //   int activeConfig = Integer.parseInt(strret2[0]);
        //   return activeConfig;
        //}

        ///**
        // *Reads information about the sensor's configuration from the integrated
        // *web server.
        // *@return  True if configuration was succesfully read, false otherwise.
        // */
        //private boolean readConfigurationInfo()
        //{
        //    try
        //    {
        //    String mDoc = readNetFTAPI(0);
        //    int activeConfig = findActiveCFG(mDoc);
        //    mDoc = readNetFTAPI(activeConfig);
        //    m_strCfgIndex = "" + activeConfig;
        //    String[] parseStep1 = mDoc.split("<cfgcalsel>");
        //    String[] parseStep2 = parseStep1[1].split("</cfgcalsel>");
        //    String mCal = readNetFTCalAPI(Integer.parseInt(parseStep2[0]));
        //    m_strCalIndex = parseStep2[0];
        //    parseStep1 = mCal.split("<calsn>");
        //    parseStep2 = parseStep1[1].split("</calsn>");
        //    m_strCalSN = parseStep2[0];
        //    mDoc = readNetFTAPI(activeConfig);
        //    parseStep1 = mDoc.split("<cfgnam>");
        //    parseStep2 = parseStep1[1].split("</cfgnam>");
        //    m_strCfgName = parseStep2[0];
        //    parseStep1 = mDoc.split("<cfgcpf>");
        //    parseStep2 = parseStep1[1].split("</cfgcpf>");
        //    setCountsPerForce(Double.parseDouble(parseStep2[0]));
        //    parseStep1 = mDoc.split("<cfgcpt>");
        //    parseStep2 = parseStep1[1].split("</cfgcpt>");
        //    setCountsPerTorque(Double.parseDouble(parseStep2[0]));
        //    parseStep1 = mDoc.split("<comrdtrate>");
        //    parseStep2 = parseStep1[1].split("</comrdtrate>");
        //    m_iRDTSampleRate = (Integer.parseInt(parseStep2[0]));
        //    parseStep1 = mDoc.split("<scfgfu>");
        //    parseStep2 = parseStep1[1].split("</scfgfu>");
        //    m_strForceUnits = parseStep2[0];
        //    parseStep1 = mDoc.split("<scfgtu>");
        //    parseStep2 = parseStep1[1].split("</scfgtu>");
        //    m_strTorqueUnits = parseStep2[0];
        //    parseStep1 = mDoc.split("<cfgmr>");
        //    parseStep2 = parseStep1[1].split("</cfgmr>");
        //    String[] asRatings = parseStep2[0].split(";");
        //      for ( int i = 0; i < asRatings.length; i++ )
        //      {
        //          m_daftMaxes[i] = Double.parseDouble(asRatings[i]);
        //          if ( 0 == m_daftMaxes[i])
        //          {
        //               m_daftMaxes[i] = 32768; /* Default maximum rating. */
        //          }
        //       }
        //    }catch(Exception e)
        //    {
        //        return false;
        //    }
        //    return true;
        //}

        /**
         *Sets the maximum ratings for each axis.
         *@param strConfigPageText  The HTML code of the configuration page on the
         *integrated web server.
         */

        private void setCountsPerForce(double counts)
        {
            double dCountsPerForce = counts;
            if (0 == dCountsPerForce)
            {
                dCountsPerForce = 1;
                displayError("Read a counts per force value of 0, setting it to " +
                        "1 instead.");
            }
            int i;
            for (i = 0; i < 3; i++)
            {
                m_daftCountsPerUnit[i] = dCountsPerForce;
            }
        }

        private void setCountsPerTorque(double counts)
        {
            double dCountsPerTorque = counts;
            if (0 == dCountsPerTorque)
            {
                dCountsPerTorque = 1;
                displayError("Read a counts per torque value of 0, setting it " +
                        "to 1 instead.");
            }
            int i; /*generic loop/array index.*/
            /*Precondition: dCountsPerForce has the counts per force,
             *dCountsPerTorque is the counts per torque.
             *Postcondition: m_daftCountsPerUnit has the counts per unit for each
             *axis, i == 3.
             */
            for (i = 0; i < 3; i++)
            {
                m_daftCountsPerUnit[i + 3] = dCountsPerTorque;
            }
        }

        /** This method is called from within the constructor to
         * initialize the form.
         * WARNING: Do NOT modify this code. The content of this method is
         * always regenerated by the Form Editor.
         */
        // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
        //private void initComponents() {
        //    jLabel1 = new javax.swing.JLabel();
        //    jLabel2 = new javax.swing.JLabel();
        //    jLabel3 = new javax.swing.JLabel();
        //    jLabel4 = new javax.swing.JLabel();
        //    jLabel5 = new javax.swing.JLabel();
        //    jLabel6 = new javax.swing.JLabel();
        //    lblFx = new javax.swing.JLabel();
        //    lblFy = new javax.swing.JLabel();
        //    lblFz = new javax.swing.JLabel();
        //    lblTx = new javax.swing.JLabel();
        //    lblTy = new javax.swing.JLabel();
        //    lblTz = new javax.swing.JLabel();
        //    progFx = new javax.swing.JProgressBar();
        //    progFy = new javax.swing.JProgressBar();
        //    progFz = new javax.swing.JProgressBar();
        //    progTx = new javax.swing.JProgressBar();
        //    progTy = new javax.swing.JProgressBar();
        //    progTz = new javax.swing.JProgressBar();
        //    jLabel9 = new javax.swing.JLabel();
        //    lblStatus = new javax.swing.JLabel();
        //    lblRDTSeq = new javax.swing.JLabel();
        //    jLabel8 = new javax.swing.JLabel();
        //    jLabel7 = new javax.swing.JLabel();
        //    lblFTSeq = new javax.swing.JLabel();
        //    jLabel10 = new javax.swing.JLabel();
        //    scrollErrors = new javax.swing.JScrollPane();
        //    lstErrors = new javax.swing.JList();
        //    lstErrors.setModel( new DefaultListModel() );
        //    btnCollect = new javax.swing.JButton();
        //    txtFileName = new javax.swing.JTextField();
        //    btnSelectFile = new javax.swing.JButton();
        //    lblForceUnits = new javax.swing.JLabel();
        //    lblTorqueUnits = new javax.swing.JLabel();
        //    jButton1 = new javax.swing.JButton();
        //    jLabel11 = new javax.swing.JLabel();
        //    lblConfigIndex = new javax.swing.JLabel();
        //    lblConfigName = new javax.swing.JLabel();
        //    lblCalIndex = new javax.swing.JLabel();
        //    lblCalSN = new javax.swing.JLabel();
        //    btnClear = new javax.swing.JButton();

        //    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        //    setTitle("ATI Industrial Automation Net F/T Sample");
        //    addWindowListener(new java.awt.event.WindowAdapter() {
        //        public void windowClosing(java.awt.event.WindowEvent evt) {
        //            formWindowClosing(evt);
        //        }
        //    });
        //    getContentPane().setLayout(null);

        //    jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel1.setText("Fx");
        //    getContentPane().add(jLabel1);
        //    jLabel1.setBounds(10, 50, 40, 14);

        //    jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel2.setText("Fy");
        //    getContentPane().add(jLabel2);
        //    jLabel2.setBounds(10, 80, 40, 14);

        //    jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel3.setText("Fz");
        //    getContentPane().add(jLabel3);
        //    jLabel3.setBounds(10, 110, 40, 14);

        //    jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel4.setText("Tx");
        //    getContentPane().add(jLabel4);
        //    jLabel4.setBounds(10, 140, 40, 14);

        //    jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel5.setText("Ty");
        //    getContentPane().add(jLabel5);
        //    jLabel5.setBounds(10, 170, 40, 14);

        //    jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel6.setText("Tz");
        //    getContentPane().add(jLabel6);
        //    jLabel6.setBounds(10, 200, 40, 14);

        //    lblFx.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblFx.setText("0");
        //    lblFx.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblFx);
        //    lblFx.setBounds(60, 50, 100, 18);

        //    lblFy.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblFy.setText("0");
        //    lblFy.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblFy);
        //    lblFy.setBounds(60, 80, 100, 18);

        //    lblFz.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblFz.setText("0");
        //    lblFz.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblFz);
        //    lblFz.setBounds(60, 110, 100, 18);

        //    lblTx.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblTx.setText("0");
        //    lblTx.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblTx);
        //    lblTx.setBounds(60, 140, 100, 18);

        //    lblTy.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblTy.setText("0");
        //    lblTy.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblTy);
        //    lblTy.setBounds(60, 170, 100, 18);

        //    lblTz.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblTz.setText("0");
        //    lblTz.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblTz);
        //    lblTz.setBounds(60, 200, 100, 18);
        //    getContentPane().add(progFx);
        //    progFx.setBounds(170, 50, 310, 19);
        //    getContentPane().add(progFy);
        //    progFy.setBounds(170, 80, 310, 19);
        //    getContentPane().add(progFz);
        //    progFz.setBounds(170, 110, 310, 19);
        //    getContentPane().add(progTx);
        //    progTx.setBounds(170, 140, 310, 19);
        //    getContentPane().add(progTy);
        //    progTy.setBounds(170, 170, 310, 19);
        //    getContentPane().add(progTz);
        //    progTz.setBounds(170, 200, 310, 19);

        //    jLabel9.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel9.setText("Status");
        //    getContentPane().add(jLabel9);
        //    jLabel9.setBounds(10, 20, 40, 14);

        //    lblStatus.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblStatus.setText("0");
        //    lblStatus.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblStatus);
        //    lblStatus.setBounds(60, 20, 100, 18);

        //    lblRDTSeq.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblRDTSeq.setText("0");
        //    lblRDTSeq.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblRDTSeq);
        //    lblRDTSeq.setBounds(225, 20, 100, 18);

        //    jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel8.setText("RDTSeq");
        //    getContentPane().add(jLabel8);
        //    jLabel8.setBounds(165, 20, 50, 14);

        //    jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    jLabel7.setText("FTSeq");
        //    getContentPane().add(jLabel7);
        //    jLabel7.setBounds(330, 20, 40, 14);

        //    lblFTSeq.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        //    lblFTSeq.setText("0");
        //    lblFTSeq.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        //    getContentPane().add(lblFTSeq);
        //    lblFTSeq.setBounds(380, 20, 100, 18);

        //    jLabel10.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        //    jLabel10.setText("Errors");
        //    getContentPane().add(jLabel10);
        //    jLabel10.setBounds(10, 460, 60, 14);

        //    scrollErrors.setOpaque(false);
        //    scrollErrors.setPreferredSize(new java.awt.Dimension(100, 100));

        //    lstErrors.setForeground(new java.awt.Color(255, 0, 0));
        //    scrollErrors.setViewportView(lstErrors);

        //    getContentPane().add(scrollErrors);
        //    scrollErrors.setBounds(10, 480, 500, 90);

        //    btnCollect.setText("Collect Streaming");
        //    btnCollect.addActionListener(new java.awt.event.ActionListener() {
        //        public void actionPerformed(java.awt.event.ActionEvent evt) {
        //            btnCollectActionPerformed(evt);
        //        }
        //    });
        //    getContentPane().add(btnCollect);
        //    btnCollect.setBounds(10, 430, 180, 23);

        //    txtFileName.setText("<please select a file>");
        //    getContentPane().add(txtFileName);
        //    txtFileName.setBounds(10, 400, 240, 20);

        //    btnSelectFile.setText("...");
        //    btnSelectFile.addActionListener(new java.awt.event.ActionListener() {
        //        public void actionPerformed(java.awt.event.ActionEvent evt) {
        //            btnSelectFileActionPerformed(evt);
        //        }
        //    });
        //    getContentPane().add(btnSelectFile);
        //    btnSelectFile.setBounds(260, 400, 30, 20);

        //    lblForceUnits.setText("Force units: ?");
        //    getContentPane().add(lblForceUnits);
        //    lblForceUnits.setBounds(10, 280, 180, 14);

        //    lblTorqueUnits.setText("Torque units: ?");
        //    getContentPane().add(lblTorqueUnits);
        //    lblTorqueUnits.setBounds(10, 300, 180, 14);

        //    jButton1.setText("Bias");
        //    jButton1.addActionListener(new java.awt.event.ActionListener() {
        //        public void actionPerformed(java.awt.event.ActionEvent evt) {
        //            jButton1ActionPerformed(evt);
        //        }
        //    });
        //    getContentPane().add(jButton1);
        //    jButton1.setBounds(10, 240, 70, 23);

        //    jLabel11.setText("<HTML>Rotate cube by dragging mouse</HTML>");
        //    getContentPane().add(jLabel11);
        //    jLabel11.setBounds(190, 230, 100, 40);

        //    lblConfigIndex.setText("Config Index: ?");
        //    getContentPane().add(lblConfigIndex);
        //    lblConfigIndex.setBounds(10, 320, 180, 14);

        //    lblConfigName.setText("Config Name: ?");
        //    getContentPane().add(lblConfigName);
        //    lblConfigName.setBounds(10, 340, 290, 14);

        //    lblCalIndex.setText("Calibration Index: ?");
        //    getContentPane().add(lblCalIndex);
        //    lblCalIndex.setBounds(10, 360, 190, 14);

        //    lblCalSN.setText("Calibration Serial#: ?");
        //    getContentPane().add(lblCalSN);
        //    lblCalSN.setBounds(10, 380, 300, 14);

        //    btnClear.setText("Clear");
        //    btnClear.addActionListener(new java.awt.event.ActionListener() {
        //        public void actionPerformed(java.awt.event.ActionEvent evt) {
        //            btnClearPerformed(evt);
        //        }
        //    });
        //    getContentPane().add(btnClear);
        //    btnClear.setBounds(393, 450, 110, 23);

        //    java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        //    setBounds((screenSize.width-528)/2, (screenSize.height-632)/2, 528, 632);
        //}// </editor-fold>//GEN-END:initComponents

        //private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        //    try{
        //        m_netFT.tare();
        //    }catch(SocketException sexc){
        //        displayError( "SocketException: " + sexc.getMessage());
        //    }catch(IOException ioexc){
        //        displayError("IOException: " + ioexc.getMessage());
        //    }
        //}//GEN-LAST:event_jButton1ActionPerformed

        //private void btnCollectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCollectActionPerformed
        //    /*synchronize to avoid stopping the data collection in the middle
        //     *of trying to read data in the NetFTReaderThread*/
        //    synchronized ( m_netFT ){
        //        m_bDoingHighSpeedCollection = !m_bDoingHighSpeedCollection;
        //        /*if we were collecting data, stop it now*/
        //        if ( !m_bDoingHighSpeedCollection ){
        //            btnCollect.setText( "Start Collecting" );
        //            try{
        //                m_netFT.stopDataCollection( m_cNetFTDataSocket );
        //                m_cDataWriter.close();
        //            }catch ( IOException cIOexc ){
        //                displayError( "IOException: " + cIOexc.getMessage() );
        //            }
        //            /*go back to reading single data points in slow mode*/
        //            stopAndRestartSingleReadings();
        //            return;
        //        }
        //        stopReaderThread();
        //    }

        //    try{
        //        m_cDataWriter = new PrintWriter( new FileWriter(
        //                txtFileName.getText() ) );
        //        Calendar curTime = Calendar.getInstance();
        //        String dateTimeString = DateFormat.getDateTimeInstance(
        //                DateFormat.SHORT, DateFormat.SHORT ).format(
        //                curTime.getTime() );
        //        m_cDataWriter.println( "Start Time: " + dateTimeString );
        //        m_cDataWriter.println( "RDT Sample Rate: " + m_iRDTSampleRate);
        //        m_cDataWriter.println( lblForceUnits.getText() );
        //        m_cDataWriter.println( "Counts per Unit Force: " +
        //                m_daftCountsPerUnit[0] );
        //        m_cDataWriter.println( lblTorqueUnits.getText() );
        //        m_cDataWriter.println( "Counts per Unit Torque: " +
        //                m_daftCountsPerUnit[3] );
        //        m_cDataWriter.println( "Status (hex), RDTSequence, F/T Sequence, Fx, Fy, Fz," +
        //                " Tx, Ty, Tz, Time" );
        //    }catch ( IOException cIOExc ){
        //        /*if we can't open the file, don't do data collection*/
        //        displayError( "IOException: " + cIOExc.getMessage() );
        //        m_bDoingHighSpeedCollection = false;
        //        stopAndRestartSingleReadings();
        //        return;
        //    }

        //    /*we're starting a new round of high-speed data collection*/
        //    btnCollect.setText( "Stop Collecting" );

        //    /*set count to infinity - we'll stop collecting when the user
        //     *presses the "Stop Collecting" button*/
        //    try{
        //        m_cNetFTDataSocket = m_netFT.startHighSpeedDataCollection(
        //                0 );
        //    }catch ( SocketException cSexc ){
        //        displayError( "SocketException: " + cSexc.getMessage() );
        //    }catch ( IOException cIOexc ){
        //        displayError( "IOException" + cIOexc.getMessage() );
        //    }
        //    m_NetFTReaderThread = new NetFTReaderThread( m_netFT, this );
        //    m_NetFTReaderThread.start();
        //}//GEN-LAST:event_btnCollectActionPerformed

        //private void btnSelectFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSelectFileActionPerformed
        //    /*the file dialog used to choose the file to save data in.*/
        //    FileDialog cDataFileChooser = new FileDialog( this,
        //            "Choose File to Save Data to", FileDialog.SAVE );
        //    cDataFileChooser.setVisible( true );
        //    if ( null == cDataFileChooser.getFile() ){
        //        return;
        //    }
        //    txtFileName.setText( cDataFileChooser.getDirectory() + cDataFileChooser.getFile() );

        //}//GEN-LAST:event_btnSelectFileActionPerformed

        private void formWindowClosing(object sender, FormClosingEventArgs e)
        {//GEN-FIRST:event_formWindowClosing
            stopReaderThread();
            try
            {
                if (m_bDoingHighSpeedCollection)
                {
                    m_netFT.stopDataCollection(m_cNetFTDataSocket);
                }
            }
            catch (IOException ioexc)
            {
                MessageBox.Show("An IOException has " + "occurred: " + ioexc.Message, "IOException");
            }
        }//GEN-LAST:event_formWindowClosing

        //private void btnClearPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearPerformed
        //// TODO add your handling code here:
        //    lstErrors.setModel(new DefaultListModel());
        //}//GEN-LAST:event_btnClearPerformed

        //    /**Starts GUI
        //     * @param args the command line arguments
        //     */
        //    public static void main(String args[]) {
        //        java.awt.EventQueue.invokeLater(new Runnable() {
        //            public void run() {
        //                new NetFTSampleGUI().setVisible(true);
        //            }
        //        });
        //    }

        /**Updates the error display with a specific error message.
         */
        //private class UpdateErrorDisplay implements Runnable{
        //    private String m_sErrDesc; /*the error description*/

        //    /**displays the error text*/
        //    public void run(){
        //        Calendar curTime = Calendar.getInstance();
        //        String errString = DateFormat.getTimeInstance(
        //                DateFormat.MEDIUM ).format( curTime.getTime() ) + " - " +
        //                m_sErrDesc;
        //        DefaultListModel errListModel =
        //                (DefaultListModel)lstErrors.getModel(); /*contains the list
        //                 *of errors*/
        //        errListModel.add( 0, errString );

        //    }

        //    /**Creates a new UpdateErrorDisplay.
        //     *@param setErrDesc     The String describing the error
        //     */
        //    public UpdateErrorDisplay( String setErrDesc ){
        //        m_sErrDesc = setErrDesc;
        //    }
        //}

        /**Display an error in the last error field, including the time that
         *the error occurred.  Does the displaying using InvokeLater, so it's
         *thread safe.
         *@param errDesc    The String to display in the last error field.  The
         *time will be displayed in front of this text, so there is no need to put
         *the time in yourself.
         */
        public void displayError(String errDesc)
        {
            Console.WriteLine("error: " + errDesc);
            //Runnable updateDisplay = new UpdateErrorDisplay( errDesc );
            //javax.swing.SwingUtilities.invokeLater( updateDisplay );
        }

        /**Runnable which updates the Force and Torque display using data
         *from an RDT packet.  Used exclusively by the DisplayFTData method.
         */
        //private class UpdateFTDisplay
        //{
        //    private NetFTRDTPacket m_rdtPacket;

        //    /**Creates a new UpdateFTDisplay
        //     *@param setRDTPacket   The NetFTRDTPacket which contains the
        //     *F/T data to display.
        //     */
        //    public UpdateFTDisplay( NetFTRDTPacket setRDTPacket ){
        //        m_rdtPacket = setRDTPacket;
        //    }

        //    public void run(){
        //        lblStatus.setText( "0x" + String.format(  "%08x",
        //            (int)m_rdtPacket.getStatus() ) );
        //        lblRDTSeq.setText( "" + m_rdtPacket.getRDTSequence() );
        //        lblFTSeq.setText( "" + m_rdtPacket.getFTSequence() );
        //        int ftCountsReading[] = m_rdtPacket.getFTArray();
        //        double ftRealReading[] = new double[NUM_FT_AXES];
        //        int i;
        //        for ( i = 0; i < NUM_FT_AXES; i++)
        //        {
        //            /*display the numbers*/
        //            ftRealReading[i] = ftCountsReading[i] / m_daftCountsPerUnit[i];

        //            m_lblaFTLabel[i].setText( m_dfReading.format( ftRealReading[i] ) );
        //            if ( ftRealReading[i] < 0)
        //                m_progaFTReadingBar[i].setForeground( NEGATIVE_COLOR );
        //            else
        //                m_progaFTReadingBar[i].setForeground( POSITIVE_COLOR );
        //            m_progaFTReadingBar[i].setValue( (int)Math.abs( ftRealReading[i] /
        //                m_daftMaxes[i] * 100 ) );
        //        }
        //    }
        //}

        /**Displays new F/T data using InvokeLater, so it's thread-safe
         *@param displayRDT - the NetFTRDTPacket containing the F/T data to
         *display
         */
        public void displayFTData(NetFTRDTPacket displayRDT, TextBox box)
        {
            box.Clear();
            box.AppendText("0x" + String.Format("%08x", (int)displayRDT.getStatus()) + "\n");
            box.AppendText("" + displayRDT.getRDTSequence() + "\n");
            box.AppendText("" + displayRDT.getFTSequence() + "\n");
            int[] ftCountsReading = displayRDT.getFTArray();
            double[] ftRealReading = new double[NUM_FT_AXES];
            int i;
            for (i = 0; i < NUM_FT_AXES; i++)
            {
                /*display the numbers*/
                ftRealReading[i] = ftCountsReading[i] / m_daftCountsPerUnit[i];

                box.AppendText(ftRealReading[i].ToString("#.000") + "\n");
                //if ( ftRealReading[i] < 0)
                //    m_progaFTReadingBar[i].setForeground( NEGATIVE_COLOR );
                //else
                //    m_progaFTReadingBar[i].setForeground( POSITIVE_COLOR );
                //box.AppendText.setValue( (int)Math.abs( ftRealReading[i] /
                //    m_daftMaxes[i] * 100 ) );
            }
            //UpdateFTDisplay updater = new UpdateFTDisplay( displayRDT );
            //javax.swing.SwingUtilities.invokeLater( updater );
        }

        /**This method gets the latest force and torque values, and displays
         *them on the screen.
         */
        private void GetFTValues()
        {
            NetFTRDTPacket rdtData;
            try
            {
                rdtData = m_netFT.readSingleFTRecord(outputBox);
            }
            catch (SocketException sexc)
            {
                displayError("SocketException: " + sexc.Message);
                return;
            }
            catch (IOException iexc)
            {
                displayError("IOException: " + iexc.Message);
                return;
            }
        }

        // Variables declaration - do not modify//GEN-BEGIN:variables
        //private javax.swing.JButton btnClear;
        //private javax.swing.JButton btnCollect;
        //private javax.swing.JButton btnSelectFile;
        //private javax.swing.JButton jButton1;
        //private javax.swing.JLabel jLabel1;
        //private javax.swing.JLabel jLabel10;
        //private javax.swing.JLabel jLabel11;
        //private javax.swing.JLabel jLabel2;
        //private javax.swing.JLabel jLabel3;
        //private javax.swing.JLabel jLabel4;
        //private javax.swing.JLabel jLabel5;
        //private javax.swing.JLabel jLabel6;
        //private javax.swing.JLabel jLabel7;
        //private javax.swing.JLabel jLabel8;
        //private javax.swing.JLabel jLabel9;
        //private javax.swing.JMenu jMenu1;
        //private javax.swing.JMenuBar jMenuBar1;
        //private javax.swing.JMenuItem jMenuItem1;
        //private javax.swing.JLabel lblCalIndex;
        //private javax.swing.JLabel lblCalSN;
        //private javax.swing.JLabel lblConfigIndex;
        //private javax.swing.JLabel lblConfigName;
        //private javax.swing.JLabel lblFTSeq;
        //private javax.swing.JLabel lblForceUnits;
        //private javax.swing.JLabel lblFx;
        //private javax.swing.JLabel lblFy;
        //private javax.swing.JLabel lblFz;
        //private javax.swing.JLabel lblRDTSeq;
        //private javax.swing.JLabel lblStatus;
        //private javax.swing.JLabel lblTorqueUnits;
        //private javax.swing.JLabel lblTx;
        //private javax.swing.JLabel lblTy;
        //private javax.swing.JLabel lblTz;
        //private javax.swing.JList lstErrors;
        //private javax.swing.JProgressBar progFx;
        //private javax.swing.JProgressBar progFy;
        //private javax.swing.JProgressBar progFz;
        //private javax.swing.JProgressBar progTx;
        //private javax.swing.JProgressBar progTy;
        //private javax.swing.JProgressBar progTz;
        //private javax.swing.JScrollPane scrollErrors;
        //private javax.swing.JTextField txtFileName;
        // End of variables declaration//GEN-END:variables

        public void print(string output) { this.outputBox.AppendText(output + "\n"); }

        public Form1()
        {
            InitializeComponent();

            outputBox.AppendText("new\n");

            //m_dfReading = new DecimalFormat( "#.000");
            //m_lblaFTLabel = new JLabel[] { lblFx, lblFy, lblFz, lblTx, lblTy,
            //lblTz };
            //m_progaFTReadingBar = new JProgressBar[] { progFx, progFy, progFz,
            //progTx, progTy, progTz };
            m_strSensorAddress = "146.232.146.253";
            //m_strSensorAddress = JOptionPane.showInputDialog( this, "What is " +
            //"the address of the sensor?", "Sensor Address",
            //JOptionPane.QUESTION_MESSAGE);
            //this.setTitle(m_strSensorAddress + " - ATINetFT Demo");
            //        URL urlIconPath = getClass().getResource("ATIFTSADemo_1.jpg"); //ClassLoader.getSystemClassLoader().getSystemResource("ati1.ico");
            stopAndRestartSingleReadings();
        }
    }
}